package add_$14_Deadlock;

/*

1、禁止一个线程持同时持有多个锁
父亲不要同时对lock1和lock2进行锁定等等
2、具备相同的加锁顺序
父亲先拿lock1再拿lock2儿子也先拿lock1再拿lock2
3、设置锁超时
现实业务中，一个线程拿到锁后最好设置锁过期，因为业务异常或者其他原因长时间持久锁时，锁会自动过期，有效避免死锁。
4、死锁检测
使用一定算法拿锁前，先检测会不会发生死锁，如果会就不去拿该锁(适用相同加锁顺序和锁超时都无法使用的场景)

 */

public class SolveDeadlock {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        DeadlockThread1 d1 = new DeadlockThread1(true);
        DeadlockThread1 d2 = new DeadlockThread1(false);
        new Thread(d1, "日本人").start();
        new Thread(d2, "美国人").start();
    }

}

class DeadlockThread1 implements Runnable {
    static Object chopsticks = new Object();
    static Object knifeAndFork = new Object();
    private boolean flag;

    DeadlockThread1(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        if (flag) {
            synchronized (knifeAndFork) {
                System.out.println(Thread.currentThread().getName() + "说：“我拿到刀叉了！你先给我筷子，我再给你刀叉！”");
                synchronized (chopsticks) {
                    System.out.println(Thread.currentThread().getName() + "说：“我拿到筷子了！");
                }
            }

        } else {

            synchronized (knifeAndFork) {
                System.out.println(Thread.currentThread().getName() + "说：“我拿到筷子了！你先给我刀叉，我再给你筷子！”");
                synchronized (chopsticks) {
                    System.out.println(Thread.currentThread().getName() + "说：“我拿到刀叉了！”");
                }
            }
        }
    }
}